#include "renderwidget.h"
#include "bmdcore.h"

RenderWidget::RenderWidget(QWidget *parent) :
    QGLWidget(parent),pMainTimer(new QBasicTimer),m_mm(0)
{

}

RenderWidget::~RenderWidget()
{
    delete pMainTimer;
}

void RenderWidget::SetMeshManager(MeshManager *mm)
{
    m_mm = mm;
    if(m_bInitialzed)
        UploadMesh();
}

void RenderWidget::initializeGL()
{
    glEnable(GL_DEPTH_TEST);

    m_program.addShaderFromSourceFile(QGLShader::Vertex, ":/shader/base.vsh");
    m_program.addShaderFromSourceFile(QGLShader::Fragment, ":/shader/base.fsh");
    m_program.link();

    m_va_vertices = m_program.attributeLocation("va_vertices");
    m_va_normals = m_program.attributeLocation("va_normals");

    m_vu_view = m_program.uniformLocation("vu_view");
    m_vu_model = m_program.uniformLocation("vu_model");
    m_vu_normal = m_program.uniformLocation("vu_normal");

    m_vu_eyepos = m_program.uniformLocation("vu_eyepos");

    m_vu_isPoint = m_program.uniformLocation("vu_isPoint");
    m_vu_pointColor = m_program.uniformLocation("vu_pointColor");
    m_vu_pointSize = m_program.uniformLocation("vu_pointSize");

    m_program.bind();

    m_program.setUniformValue("m_diffuse",QVector4D(.3f,.3f,.3f,1.f));
    m_program.setUniformValue("m_ambient",QVector4D(.9f,.9f,.9f,1.f));
    m_program.setUniformValue("m_specular",QVector4D(.6f,.6f,.6f,1.f));

    m_program.setUniformValue("l_ambient",QVector4D(0.5f,0.5f,0.f,1.f));
    m_program.setUniformValue("l_diffuse",QVector4D(.5f,.5f,0.5f,1.f));
    m_program.setUniformValue("l_specular",QVector4D(.8f,.8f,.8f,1.f));

    m_program.setUniformValue("l_position",QVector4D(150.f,150.f,200.f,1.0f));

    m_bInitialzed = true;
    if (m_mm!=0)
        UploadMesh();

    pMainTimer->start(12,this);
}

void RenderWidget::resizeGL(int w, int h)
{
    glViewport(0,0,w,h);
    m_proj.setToIdentity();
    m_proj.perspective(45.0f,float(w)/float(h),0.1f,1000.0f);
    m_program.setUniformValue("vu_proj",m_proj);
}

float r = 0;
void RenderWidget::paintGL()
{
    glClearColor(0.2f,0.2f,0.2f,1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    m_model.setToIdentity();
    m_model.translate(0,0,0);
    m_model.rotate(r,0,1,0);
//    m_model.rotate(r,1,0,0);
    r+=0.5f;

    m_program.setUniformValue(m_vu_view, m_view);
    m_program.setUniformValue(m_vu_model, m_model);
    m_program.setUniformValue(m_vu_normal, (m_view*m_model).inverted().transposed());
    m_program.setUniformValue(m_vu_eyepos, m_eye-m_center);

    m_program.enableAttributeArray(m_va_vertices);
    m_program.enableAttributeArray(m_va_normals);

    m_program.setUniformValue(m_vu_isPoint,false);
    m_program.setUniformValue(m_vu_pointSize,1.5f);
    m_program.setUniformValue(m_vu_pointColor, QVector4D(1.f,1.f,0.f,1.f));

    QMesh* original = m_meshes[ORIGINAL];
    original->BindArrayBuffer(QVERTEX,m_va_vertices);
    original->BindArrayBuffer(QNORMAL,m_va_normals);
    original->DrawElements(QINDICES,GL_POINTS);

    m_program.setUniformValue(m_vu_isPoint,false);
    m_program.setUniformValue(m_vu_pointSize,1.5f);
    m_program.setUniformValue(m_vu_pointColor, QVector4D(1.f,0.f,0.f,1.f));

    QOpenMesh* noised = static_cast<QOpenMesh*>(m_meshes[NOISED]);
    noised->BindArrayBuffer(QVERTEX,m_va_vertices);
    noised->BindArrayBuffer(QNORMAL,m_va_normals);
    noised->DrawElements(QINDICES,GL_TRIANGLES);

    m_program.disableAttributeArray(m_va_vertices);
    m_program.disableAttributeArray(m_va_normals);
}

void RenderWidget::timerEvent(QTimerEvent *e)
{
    Q_UNUSED(e);
    updateGL();
}
